package com.atguigu.gmall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.entity.CartItem;
import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.GmallConstant;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.feign.interceptor.AuthUserInfo;
import com.atguigu.gmall.common.feign.product.SkuFeignClient;
import com.atguigu.gmall.common.feign.util.AuthUserInfoUtils;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.product.entity.SkuInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate<String , String> redisTemplate ;

    @Autowired
    private SkuFeignClient skuFeignClient;

    @Override
    public List<CartItem> findAllCartItem() {
        // 判断当前用户是否登录
        AuthUserInfo authUserInfo = AuthUserInfoUtils.getAuthUserInfo();
        String userId = authUserInfo.getUserId();//拿到用户id
        if (!StringUtils.isEmpty(userId)){//已经登录

            // 构建临时购物车的数据key
            String userTempCartRediskey = GmallConstant.REDIS_CART_PRE + authUserInfo.getUserTempId();
            // 构建购物车的数据key
            String userCartRediskey = GmallConstant.REDIS_CART_PRE + authUserInfo.getUserId();

            // 获取临时购物车数据
            List<CartItem> userTempCartItemList = redisTemplate.opsForHash().values(userTempCartRediskey).stream().map(obj -> {
                //转成json字符串
                String cartItemJSON = obj.toString();
                CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
                return cartItem;
            }).collect(Collectors.toList());
            //获取用户购物车数据
            List<Long> userCartSkuIds = redisTemplate.opsForHash().values(userCartRediskey).stream().map(obj -> {
                String cartItemJSON = obj.toString();
                CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
                return cartItem.getSkuId();
            }).collect(Collectors.toList());

            //拿到临时购物车的全部id
            List<Long> userTempCartSkuIds = userTempCartItemList.stream().map(tempCartItem -> tempCartItem.getSkuId()).collect(Collectors.toList());

            // 合并集合并进行去重
            List<Long> collect = Stream.concat(userCartSkuIds.stream(), userTempCartSkuIds.stream()).distinct().collect(Collectors.toList());
            if (collect.size() > 3){
                throw new GmallException(ResultCodeEnum.CART_ITEM_NUMBER_ERROR) ;
            }

            // 对临时购物车列表进行遍历，获取每一个购物项数据，然后将其添加到用户购物车中
            for (CartItem cartItem : userTempCartItemList){
                //拿到每个购物车数据项的skuID
                Long skuId = cartItem.getSkuId();
                //根据这些skuId 查询真正购物车中是否有对应的数据
                Boolean hasKey = redisTemplate.opsForHash().hasKey(userCartRediskey, String.valueOf(skuId));
                if (hasKey){//说明购物车里有这个商品

                    String userCartItemJSON = redisTemplate.opsForHash().get(userCartRediskey, String.valueOf(skuId)).toString();
                    CartItem userCartItem = JSON.parseObject(userCartItemJSON, CartItem.class);//购物车的商品
                    userCartItem.setSkuNum(userCartItem.getSkuNum() + cartItem.getSkuNum());
                    //拿到skuNum 对他的数量进行限制处理
                    Integer skuNum = userCartItem.getSkuNum();
                    if (skuNum > 10){
                        userCartItem.setSkuNum(10);
                    }
                    redisTemplate.opsForHash().put(userCartRediskey , String.valueOf(skuId) , JSON.toJSONString(userCartItem));

                }else { //如果没有这个商品 大key用的是真实购物车的 小key是临时购物车的 因为是把临时购物车中的数据添加进去
                    redisTemplate.opsForHash().put( userCartRediskey, String.valueOf(skuId) , JSON.toJSONString(cartItem));
                }
            }
            //删除临时购物车
            redisTemplate.delete(userTempCartRediskey);

            // 获取用户购物车数据进行返回
            List<CartItem> cartItemList = redisTemplate.opsForHash().values(userCartRediskey).stream().map(ojb -> {
                String cartItemJSON = ojb.toString();
                CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
                //更新价格
                updateSkuPrice(cartItem , userCartRediskey);
                return cartItem;
            }).collect(Collectors.toList());
            return cartItemList ;
        }else {     //未登录
            String redisKey = buildRedisKey();
            List<Object> objectList = redisTemplate.opsForHash().values(redisKey);
            //得到的数据类型 不是想要的 所以对他进行处理 用stream流
            List<CartItem> cartItemList = objectList.stream().map(obj -> {
                String cartItemJSON = obj.toString();
                CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);

                //查看购物车时更新价格的新数据
                updateSkuPrice(cartItem , redisKey);

                return cartItem;
            }).collect(Collectors.toList());
            return cartItemList;
        }

    }

    // 更新Redis中商品的价格
    private void updateSkuPrice(CartItem cartItem, String redisKey) {

        Result<SkuInfo> skuInfoBySkuId = skuFeignClient.findSkuInfoBySkuId(cartItem.getSkuId());
        SkuInfo skuInfo = skuInfoBySkuId.getData();
        cartItem.setSkuPrice(skuInfo.getPrice());

        //更新后的数据 写入到redis中
        redisTemplate.opsForHash().put(redisKey , String.valueOf(cartItem.getSkuId()) , JSON.toJSONString(cartItem));
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //构建redis的key
        String redisKey = buildRedisKey();
        //得到JSON字符串数据
        String cartItemJSON = redisTemplate.opsForHash().get(redisKey, String.valueOf(skuId)).toString();
        //转换类型 得到cartItem
        CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
        //拿到skuNum数据
        Integer cartItemSkuNum = cartItem.getSkuNum();
        cartItem.setSkuNum(cartItemSkuNum + skuNum);//对他进行相加操作


        //对商品数量进行控制
        if (cartItemSkuNum > 10){
            cartItem.setSkuNum(10);
        }

        redisTemplate.opsForHash().put(redisKey , String.valueOf(skuId) , JSON.toJSONString(cartItem));

    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        String redisKey = buildRedisKey();
        String cartItemJSON = redisTemplate.opsForHash().get(redisKey, String.valueOf(skuId)).toString();
        CartItem cartItem = JSON.parseObject(cartItemJSON, CartItem.class);
        //把前端传过来的isChecked设置进去
        cartItem.setIsChecked(isChecked);
        redisTemplate.opsForHash().put(redisKey , String.valueOf(skuId) , JSON.toJSONString(cartItem));
    }

    @Override
    public void deleteCart(Long skuId) {
        String redisKey = buildRedisKey();
        redisTemplate.opsForHash().delete(redisKey , String.valueOf(skuId));
    }

    //构建redis中 关于购物车数据的key
    private String buildRedisKey() {

        //封装了用户的id和临时用户的id
        AuthUserInfo authUserInfo = AuthUserInfoUtils.getAuthUserInfo();
        if(authUserInfo != null) {
            String userId = authUserInfo.getUserId();
            String userTempId = authUserInfo.getUserTempId();
            if(!StringUtils.isEmpty(userId)) {
                return GmallConstant.REDIS_CART_PRE + userId ;
            }else {
                return GmallConstant.REDIS_CART_PRE + userTempId ;
            }
        }else {
            return null ;
        }

    }

}
